package com.mysterymall.Service.Impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.mysterymall.Common.Comp.HttpStatus;
import com.mysterymall.Common.Comp.Log;
import com.mysterymall.Common.Utils.BaseEnum;
import com.mysterymall.Common.Utils.Result;
import com.mysterymall.Mapper.BrokerageDetailMapper;
import com.mysterymall.Mapper.GameCurrencyDetailMapper;
import com.mysterymall.Mapper.TeamMapper;
import com.mysterymall.Mapper.UserMapper;
import com.mysterymall.Model.Dto.TeamDto;

import java.awt.*;
import java.awt.image.BufferedImage;

import com.mysterymall.Model.Entity.BrokerageDetail;
import com.mysterymall.Model.Entity.GameCurrencyDetail;
import com.mysterymall.Model.Entity.Team;
import com.mysterymall.Model.Entity.User;
import com.mysterymall.Model.Vo.TeamInfoVo;
import com.mysterymall.Model.Vo.TeamVo;
import com.mysterymall.Model.Vo.UserVo;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.mysterymall.Service.TeamService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.imageio.ImageIO;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.*;
import java.util.List;

/**
 * @ClassName com.mysterymall.Service.Impl
 * @Description
 * @Author HuangWX
 * @Time 2023/12/02  14:02
 */
@Service
public class TeamServiceImpl implements TeamService {

    private final TeamMapper teamMapper;

    private final BrokerageDetailMapper brokerageDetailMapper;

    private final UserMapper userMapper;


    private final GameCurrencyDetailMapper gameCurrencyDetailMapper;


    /**
     * 构造器注入
     *
     * @param teamMapper 团队映射器
     */
    public TeamServiceImpl(TeamMapper teamMapper, BrokerageDetailMapper brokerageDetailMapper, UserMapper userMapper,
                           GameCurrencyDetailMapper gameCurrencyDetailMapper) {
        this.teamMapper = teamMapper;
        this.brokerageDetailMapper = brokerageDetailMapper;
        this.userMapper = userMapper;
        this.gameCurrencyDetailMapper = gameCurrencyDetailMapper;
    }


    /**
     * 获取团队列表
     *
     * @param page 页码
     * @param size 每页数量
     * @return Result
     */
    @Override
    public Result getTeamList(Integer page, Integer size) {

        if (!StpUtil.hasPermission("team:select:*")) {
            return new Result(HttpStatus.UNAUTHORIZED, "message.powerError");
        }

        List<TeamVo> teamVoList = new ArrayList<>(size);

        Page<Team> teamPage = teamMapper.selectPage(new Page<>(page, size), new LambdaQueryWrapper<Team>().orderByDesc(Team::getAccumulateAmount));


        for (Team team : teamPage.getRecords()) {
            TeamVo teamVo = new TeamVo();
            BeanUtils.copyProperties(team, teamVo);
            teamVo.setTeamCount(brokerageDetailMapper.selectCount(new LambdaQueryWrapper<BrokerageDetail>().eq(BrokerageDetail::getTeamId, team.getId())));
            teamVoList.add(teamVo);
        }

        Map<String, Object> map = new HashMap<>(2);
        map.put("teamList", teamVoList);
        map.put("total", teamPage.getTotal());

        return Result.success("message.querySuccess", map);
    }


    /**
     * 修改团队
     *
     * @param teamDto 团队实体
     * @return Result
     */
    @Override
    public Result updateTeam(TeamDto teamDto) {

        if (!StpUtil.hasPermission("team:update:*")) {
            return new Result(HttpStatus.UNAUTHORIZED, "message.powerError");
        }

        Team team = teamMapper.selectById(teamDto.getId());

        // 校验
        if (team == null) {
            return new Result(HttpStatus.BAD_REQUEST, "message.updateError");
        }

        teamMapper.updateById(team);

        return Result.success("message.updateSuccess");
    }

    @Override
    public Result getMyBrokerageDetail(Integer page, Integer size) {

        User user = userMapper.selectById(StpUtil.getLoginIdAsString());

        Map<String, Object> map = new HashMap<>(2);
        // 查询我的团队
        Team team = teamMapper.selectOne(new LambdaQueryWrapper<Team>().eq(Team::getCreateUser, user.getId()));

        if (team == null) {
            map.put("brokerageDetailList", new ArrayList<>());
            map.put("brokerage", user.getBrokerage());
            return Result.success("message.querySuccess", map);
        }

        Page<BrokerageDetail> brokerageDetailPage = brokerageDetailMapper.selectPage(new Page<>(page, size), new LambdaQueryWrapper<BrokerageDetail>().eq(BrokerageDetail::getTeamId, team.getId()));
        // 查询明细
        List<BrokerageDetail> brokerageDetailList = brokerageDetailPage.getRecords();

        List<BrokerageDetail> brokerageDetailList1 = new ArrayList<>();
        for (BrokerageDetail brokerageDetail : brokerageDetailList) {
            User user1 = userMapper.selectById(brokerageDetail.getUserId());
            brokerageDetail.setUserId(user1.getUserName());
            brokerageDetailList1.add(brokerageDetail);
        }

        // 查询明细
        map.put("brokerageDetailList", brokerageDetailList1);
        map.put("brokerage", user.getBrokerage());

        return Result.success("message.querySuccess", map);
    }

    @Override
    public Result getMyTeamList() {

        LambdaQueryWrapper<Team> teamLambdaQueryWrapper = new LambdaQueryWrapper<>();
        teamLambdaQueryWrapper.eq(Team::getCreateUser, StpUtil.getLoginIdAsString());
        teamLambdaQueryWrapper.orderByDesc(Team::getAccumulateAmount);
        List<Team> teamList = teamMapper.selectList(teamLambdaQueryWrapper);
        List<UserVo> userVoList = new ArrayList<>();
        for (Team team : teamList) {
            User user = userMapper.selectById(team.getUserId());
            UserVo userVo = new UserVo();
            BeanUtils.copyProperties(user, userVo);
            userVo.setUserName(user.getUserName());
            userVo.setUserImages("/images/" + user.getUserImages());
            userVoList.add(userVo);
        }
        return Result.success("message.querySuccess", userVoList);
    }

    @Override
    public Result getInVite(String rootUrl) throws WriterException, IOException {

        int width = 300; // 二维码图片宽度
        int height = 300; // 二维码图片高度

        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(rootUrl, BarcodeFormat.QR_CODE, width, height);

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? Color.BLACK.getRGB() : Color.WHITE.getRGB());
            }
        }
        ByteArrayOutputStream imageBase64 = new ByteArrayOutputStream();
        ImageIO.write(image, "png", imageBase64);
        byte[] imageBytes = imageBase64.toByteArray();
        return Result.success("message.querySuccess", Base64.getEncoder().encodeToString(imageBytes));
    }

    @Override
    public Result getTeamInfo(String id, Integer page, Integer size) {

        if (!StpUtil.hasPermission("team:select:*")) {
            return new Result(HttpStatus.UNAUTHORIZED, "message.powerError");
        }

        // 按照创建人查询，按照佣金倒序
        Page<Team> brokerageDetailPage = teamMapper.selectPage(new Page<>(page, size), new LambdaQueryWrapper<Team>().eq(Team::getCreateUser, id).orderByDesc(Team::getAccumulateAmount));


        // 查询累计全部佣金
        BigDecimal totalAmount = teamMapper.selectALLBrokerage(id);

        if(totalAmount == null){
            totalAmount = new BigDecimal(0);
        }

        List<TeamInfoVo> teamInfoVoList = new ArrayList<>(size);

        for (Team team : brokerageDetailPage.getRecords()) {
            TeamInfoVo teamInfoVo = new TeamInfoVo();
            User user = userMapper.selectById(team.getUserId());
            BeanUtils.copyProperties(team, teamInfoVo);
            teamInfoVo.setTotalAmount(team.getAccumulateAmount());
            teamInfoVo.setNickName(user.getNickname());
            teamInfoVo.setUserName(user.getUserName());
            teamInfoVo.setCreateTime(team.getCreateTime());
            teamInfoVoList.add(teamInfoVo);
        }

        Map<String, Object> map = new HashMap<>(3);
        map.put("teamInfoVoList", teamInfoVoList);
        map.put("total", brokerageDetailPage.getTotal());
        map.put("totalAmount", totalAmount);
        return Result.success("message.querySuccess", map);

    }

    @Override
    @Transactional
    public Result luckyCoinPayment(BigDecimal amount) {

        User user = userMapper.selectById(StpUtil.getLoginIdAsString());

        if(user.getBrokerage().compareTo(amount) < 0){
            return new Result(HttpStatus.BAD_REQUEST,"message.teamCont.brokerageError");
        }

        user.setBrokerage(user.getBrokerage().subtract(amount));

        user.setAmount(user.getAmount().add(amount));

        userMapper.updateById(user);

        GameCurrencyDetail gameCurrencyDetail = new GameCurrencyDetail();

        gameCurrencyDetail.setAmount(amount);

        gameCurrencyDetail.setUserId(user.getId());

        gameCurrencyDetail.setAmountType(BaseEnum.Game_Currency_Type_Commission_To_Game_Currency.getCode());

        gameCurrencyDetail.setGoodsName("commission_to_lucky_coin");

        gameCurrencyDetail.setType(BaseEnum.Game_Currency_Income.getCode());

        gameCurrencyDetailMapper.insert(gameCurrencyDetail);

        return Result.success("message.querySuccess");
        
    }

    @Override
    public Result addStaff(String teamUserId, String userName) {


        // 查询用户
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUserName, userName));

        if(user == null){
            return new Result(HttpStatus.BAD_NOT_PASS,"message.addError-没有查询到用户: " + userName);
        }

        // 查询用户
        User user1 = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, teamUserId));

        if(user1 == null){
            return new Result(HttpStatus.BAD_NOT_PASS,"message.addError-查询不到团长用户信息");
        }else if(user1.getId().equals(user.getId())){
            return new Result(HttpStatus.BAD_NOT_PASS,"message.addError-不能将自己添加到团队中");
        }

        // 查询是否已经是团队成员
        Team team1 = teamMapper.selectOne(new LambdaQueryWrapper<Team>().eq(Team::getUserId, user.getId()));

        if(team1 != null){
            team1.setCreateUser(teamUserId);
            team1.setAccumulateAmount(new BigDecimal(0));
            team1.setCreateTime(Instant.now());
            team1.setUpdateTime(Instant.now());
            teamMapper.updateById(team1);
        }else{
            team1 = new Team();
            team1.setUserId(user.getId());
            team1.setCreateUser(teamUserId);
            team1.setAccumulateAmount(new BigDecimal(0));
            teamMapper.insert(team1);
        }


        return new Result(HttpStatus.SUCCESS,"message.querySuccess");
    }


}
